package controller

import (
	"errors"
	"gitee.com/fierce_wolf/go-fox-edge-common/commEntityManager"
	"gitee.com/fierce_wolf/go-fox-edge-common/commRedisStatus"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Json"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Map"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Method"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/OS"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Slice"
	"gitee.com/fierce_wolf/go-fox-edge-common/edgeEntity"
	"gitee.com/fierce_wolf/go-fox-edge-common/edgeEnv"
	"gitee.com/fierce_wolf/go-fox-edge-common/httpserver"
	"go-fox-edge-kernel-manager/repository"
	"go-fox-edge-kernel-manager/utils/ProcessUtils"
)

type repoLocalApplicationController struct {
}

func (e *repoLocalApplicationController) init() {
	httpserver.Server.GET("/repository/local/app-service/status/entities", e.selectEntityList)

	httpserver.Server.GET("/repository/local/app-service/process/entities", e.getProcess)
	httpserver.Server.POST("/repository/local/app-service/process/restart", e.restartProcess)
	httpserver.Server.POST("/repository/local/app-service/process/stop", e.stopProcess)
	httpserver.Server.POST("/repository/local/app-service/process/uninstall", e.uninstallProcess)

	httpserver.Server.POST("/repository/local/app-service/config/load", e.setServiceLoad)
	httpserver.Server.PUT("/repository/local/app-service/conf", e.updateConf)
}

func (e *repoLocalApplicationController) selectEntityList(context httpserver.Context) (interface{}, error) {
	resultList := commRedisStatus.GetDataList(60 * 1000)
	return resultList, nil
}

func (e *repoLocalApplicationController) getProcess(context httpserver.Context) (interface{}, error) {
	// windows版本：不能查询进程，返回个空集合
	if OS.Type.IsWindows() {
		return make(map[string]interface{}), nil
	}

	// 从磁盘中查找所有的shell文件信息
	confFileInfoList := repository.LocalAppConf.GetConfFileInfoList()

	// 过滤掉隐藏项目
	confFileInfoList, err := repository.LocalAppConf.FilterAppConfFile(confFileInfoList)
	if err != nil {
		return nil, err
	}

	// 扩展数据库中的启动配置信息
	repository.LocalAppLoad.ExtendStartConfig(confFileInfoList)

	// 扩展相关的进程状态信息
	err = ProcessUtils.ExtendAppStatus(confFileInfoList)
	if err != nil {
		return nil, err
	}

	sysProcessList := repository.LocalAppSys.GetSysProcessList()
	confFileInfoList = Slice.Append(sysProcessList, confFileInfoList)

	return confFileInfoList, nil
}

func (e *repoLocalApplicationController) restartProcess(context httpserver.Context, body map[string]interface{}) (interface{}, error) {
	if edgeEnv.IsDockerEnv() {
		return nil, errors.New("运行环境为docker，该环境不支持该操作")
	}

	// 提取业务参数
	appName := Map.GetString(body, "appName", "")
	appType := Map.GetString(body, "appType", "")

	// 简单校验参数
	if Method.HasEmpty(appName, appType) {
		return nil, errors.New("参数不能为空:appName, appType")
	}

	// 查询启动配置项目：如果是配置未启动，那么才可以重启该进程
	appLoad := repository.LocalAppLoad.QueryServiceLoad(appName, appType, true)
	if appLoad {
		repository.LocalAppStart.RestartProcess(appName, appType)
	}

	return nil, nil
}

func (e *repoLocalApplicationController) stopProcess(context httpserver.Context, body map[string]interface{}) (interface{}, error) {
	if edgeEnv.IsDockerEnv() {
		return nil, errors.New("运行环境为docker，该环境不支持该操作")
	}

	// 提取业务参数
	appName := Map.GetString(body, "appName", "")
	appType := Map.GetString(body, "appType", "")

	// 简单校验参数
	if Method.HasEmpty(appName, appType) {
		return nil, errors.New("参数不能为空:appName, appType")
	}

	if appType == "kernel" {
		return nil, errors.New("该级别的服务不允许停止:" + appType)
	}

	// 查询启动配置项目：如果是配置未启动，那么才可以重启该进程
	repository.LocalAppStart.StopProcess(appName, appType)

	return nil, nil
}

func (e *repoLocalApplicationController) uninstallProcess(context httpserver.Context, body map[string]interface{}) (interface{}, error) {
	if edgeEnv.IsDockerEnv() {
		return nil, errors.New("运行环境为docker，该环境不支持该操作")
	}

	// 提取业务参数
	appName := Map.GetString(body, "appName", "")
	appType := Map.GetString(body, "appType", "")

	// 简单校验参数
	if Method.HasEmpty(appName, appType) {
		return nil, errors.New("参数不能为空:appName, appType")
	}

	if appType == "kernel" {
		return nil, errors.New("该级别的服务不允许删除:" + appType)
	}

	// 停止进程
	repository.CloudFileInstallService.UninstallServiceFile(appName, appType)

	return nil, nil
}

func (e *repoLocalApplicationController) setServiceLoad(context httpserver.Context, body map[string]interface{}) (interface{}, error) {
	if edgeEnv.IsDockerEnv() {
		return nil, errors.New("运行环境为docker，该环境不支持该操作")
	}

	// 提取业务参数
	appName := Map.GetString(body, "appName", "")
	appType := Map.GetString(body, "appType", "")
	appLoad := Map.GetBool(body, "appLoad", false)

	// 简单校验参数
	if Method.HasEmpty(appName, appType) || Method.HasNull(appLoad) {
		return nil, errors.New("参数不能为空:appName, appType, appLoad")
	}

	// 保存配置
	err := repository.LocalAppLoad.SaveServiceLoad(appName, appType, appLoad)
	if err != nil {
		return nil, err
	}

	// 如果修改为非启动状态，那么同时也停止进程
	if !appLoad {
		repository.LocalAppStart.StopProcess(appName, appType)
	} else {
		repository.LocalAppStart.RestartProcess(appName, appType)
	}

	return nil, nil
}

func (e *repoLocalApplicationController) updateConf(context httpserver.Context, body map[string]interface{}) (interface{}, error) {
	// 提取业务参数
	compType := Map.GetString(body, "compType", "")
	compRepo := Map.GetString(body, "compRepo", "")
	id := Map.GetInt64(body, "id", 0)
	compParam := Map.GetMap(body, "compParam", nil)

	// 简单校验参数
	if Map.HasNull(body, "id", "compParam", "compType", "compRepo") {
		return nil, errors.New("参数不能为空: id, compType, compRepo, compParam")
	}

	if compRepo != "local" || compType != "app-service" {
		return nil, errors.New("组件类型不正确")
	}

	exist := commEntityManager.GetEntityById(edgeEntity.Type.RepoCompEntity.Type(), id)
	if exist == nil {
		return nil, errors.New("实体不存在")
	}

	// 复制一个副本，避免修改到原本
	entity := edgeEntity.Type.RepoCompEntity.Instance()
	Json.Clone(exist, entity)

	appType := Map.GetString(entity.CompParam, "appType", "")
	appName := Map.GetString(entity.CompParam, "appName", "")
	if Method.HasEmpty(appName, appType) {
		return nil, errors.New("缺失参数：appName, appType")
	}

	if "kernel" == appType {
		return nil, errors.New("kernel服务不允许修改")
	}

	userParam := Map.GetString(compParam, "userParam", "")

	// 修改内容
	entity.CompParam["userParam"] = userParam

	// 保存文件
	pathName := repository.LocalPathName.GetPathName4LocalShell2confFile(appType, appName)
	repository.LocalAppConf.SaveConf(pathName, entity.CompParam)

	// 更新配置
	commEntityManager.UpdateEntity(entity)

	return nil, nil
}
